﻿#define _CRT_SECURE_NO_WARNINGS
#include "snake.h"
IMAGE img1, img2, img3;
extern int obstacle_num = 2;
extern int food_num = 3;
extern int food_eaten = 0;



void Setpos(short x, short y) {
	COORD pos = { x,y };
	HANDLE houtput = NULL;
	houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(houtput, pos);
}

void Welcome() {
	Setpos(40, 15);
	printf("欢迎来到贪吃蛇游戏！");
	Setpos(40, 25);
	system("pause");
	system("cls");
	Setpos(15, 12);
	printf("玩家1(圆形蛇身）：请用 ↑ . ↓ . ← . →分别控制蛇蛇1上下左右的移动。\n");
	Setpos(15, 14);
	printf("玩家2（方形蛇身）：请用 w . s . a . d分别控制蛇蛇2上下左右的移动。\n");
	Setpos(15, 16);
	printf("按F6加速，F7减速");
	Setpos(15, 18);
	printf("加速可获得更高的食物分数,也可让你的对手猝不及防。\n");
	Setpos(15, 20);
	printf("三角形为障碍物，星形为食物。\n");
	Setpos(15, 22);
	printf("请注意躲开三角形障碍物，争取吃到更多的星形食物。\n");
	Setpos(15, 24);
	printf("按空格键暂停游戏，按ESC键退出游戏。\n");
	Setpos(15, 26);
	printf("单人模式默认玩家1\n");
	Setpos(15, 28);
	system("pause");
	system("cls");

}


//finish
void CreateMap() {
	ConsoleTextColor(WALL_COLOR);
	int i = 0;
	//打印围墙上侧
	Setpos(0, 0);
	for (i = 0; i < 70; i += 2) {//58
		wprintf(L"%lc", WALL);
	}
	//打印围墙下侧
	Setpos(0, 35);//26
	for (i = 0; i < 70; i += 2) {//58
		wprintf(L"%lc", WALL);
	}
	//打印左边围墙
	for (i = 1; i < 35; i++) {//26
		Setpos(0, i);
		wprintf(L"%lc", WALL);
	}
	//打印右边围墙
	for (i = 1; i < 35; i++) {//26
		Setpos(68, i);//56
		wprintf(L"%lc", WALL);
	}
	ConsoleTextColor(TEXT_COLOR);
}


void InitSnake(Snake* ps, int pos_x, int pos_y, int body) {
	SnakeNode* pcur = NULL;
	for (int i = 0; i < 5; i++) {
		pcur = (SnakeNode*)malloc(sizeof(SnakeNode));
		if (pcur == NULL) {
			perror("InitSnake:malloc fail!");
			return;
		}
		pcur->next = NULL;
		pcur->x = pos_x + i * 2;
		pcur->y = pos_y;
		//头插
		if (ps->snake == NULL) {
			ps->snake = pcur;
		}
		else {
			pcur->next = ps->snake;
			ps->snake = pcur;
		}
	}
	//打印蛇身体

	pcur = ps->snake;
	while (pcur) {
		Setpos(pcur->x, pcur->y);
		if (body == 1) {
			ConsoleTextColor(SNAKE1_COLOR);
			wprintf(L"%lc", BODY1);
		}
		else {
			ConsoleTextColor(SNAKE2_COLOR);
			wprintf(L"%lc", BODY2);
		}
		pcur = pcur->next;
	}
	ps->dir = RIGHT;
	ps->status = OK;
	ps->foodweight = 10;
	ps->score = 0;
	ps->sleeptime = 200;
	ConsoleTextColor(TEXT_COLOR);
}


void CreateFood(Snake* ps1, Snake* ps2, FoodNode* pfood[15]) {
	assert(ps1);
	assert(ps2);

	food_eaten = 0;

	for (int i = 0; i < food_num; i++) {
		//确定食物位置
		int x = 0;
		int y = 0;
	again:
		do {
			x = rand() % 65 + 2;
			y = rand() % 33 + 2;
		} while (x % 2 != 0);

		SnakeNode* pcur1 = ps1->snake;
		SnakeNode* pcur2 = ps2->snake;
		while (pcur1 && pcur2) {
			if ((pcur1->x == x && pcur1->y == y) || (pcur2->x == x && pcur2->y == y)) {
				goto again;
			}
			pcur1 = pcur1->next;
			pcur2 = pcur2->next;
		}

		ConsoleTextColor(FOOD_COLOR);
		pfood[i] = (FoodNode*)malloc(sizeof(FoodNode));

		pfood[i]->x = x;
		pfood[i]->y = y;
		Setpos(pfood[i]->x, pfood[i]->y);
		wprintf(L"%c", FOOD);


	}
	ConsoleTextColor(TEXT_COLOR);
}

void GameStart(Snake* ps1, Snake* ps2) {
	system("mode con cols=160 lines=40");
	system("title 双人贪吃蛇");
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(houtput, &CursorInfo);
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(houtput, &CursorInfo);

	Welcome();
	CreateMap();
	InitSnake(ps1, POS_X1, POS_Y1, 1);
	InitSnake(ps2, POS_X1, POS_Y2, 2);
	CreateFood(ps1, ps2, pfood);
	CreateObstacle(ps1, ps2);

}

void PrintHelpInfo()
{
	//打印提⽰信息
	Setpos(80, 10);
	printf("不能穿墙，不能撞到自己,不能撞到对方\n");
	Setpos(80, 12);
	printf("玩家1(圆形蛇身）：用↑.↓.←.→分别控制蛇上下左右的移动.\n");
	Setpos(80, 14);
	printf("玩家2（方形蛇身）：用W.S.A.D分别控制蛇上下左右的移动.\n");
	Setpos(80, 16);
	printf("F6为加速，F7为减速\n");
	Setpos(80, 18);
	wprintf(L"%lc:食物， %lc:障碍物\n", FOOD, OBSTACLE);
	Setpos(80, 20);
	printf("ESC ：退出游戏.space：暂停游戏.\n");
	Setpos(80, 21);
}

void Pause()
{
	while (1)
	{
		Sleep(200);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}

void SnakeMove(Snake* ps1, Snake* ps2, int body) {//1主蛇，会被调用2次
	SnakeNode* pnext = (SnakeNode*)malloc(sizeof(SnakeNode));
	if (pnext == NULL) {
		perror("SnakeMove:malloc fail!");
		return;
	}

	switch (ps1->dir)
	{
	case UP:
		pnext->x = ps1->snake->x;
		pnext->y = ps1->snake->y - 1;
		break;
	case DOWN:
		pnext->x = ps1->snake->x;
		pnext->y = ps1->snake->y + 1;
		break;
	case LEFT:
		pnext->x = ps1->snake->x - 2;
		pnext->y = ps1->snake->y;
		break;
	case RIGHT:
		pnext->x = ps1->snake->x + 2;
		pnext->y = ps1->snake->y;
		break;
	}

	if (NextIsFood(pnext, ps1))
	{
		food_eaten++;
		PlaySound(L"SnakeEat.wav", NULL, 0);
		EatFood(pnext, ps1, ps2, body);
		
	}
	else
	{
		NoFood(pnext, ps1, body);
	}
	KillByObstacle(pnext, ps1);
	KillByWall(ps1);
	KillBySelf(ps1);
	KillByOther(ps1, ps2);
}

int NextIsFood(SnakeNode* pnext, Snake* ps) {

	for (int i = 0; i < 15; i++) {
		if (pfood[i]) {
			if ((pnext->x == pfood[i]->x) && (pnext->y == pfood[i]->y)) {
				pfood[i]->x = 0;
				pfood[i]->y = 0;
				return 1;
			}
		}
	}

	return 0;
}

void EatFood(SnakeNode* pnext, Snake* ps1, Snake* ps2, int body) {
	pnext->next = ps1->snake;
	ps1->snake = pnext;

	SnakeNode* pcur = ps1->snake;
	while (pcur) {
		Setpos(pcur->x, pcur->y);
		if (body == 1) {
			ConsoleTextColor(SNAKE1_COLOR);
			wprintf(L"%c", BODY1);
		}
		else {
			ConsoleTextColor(SNAKE2_COLOR);
			wprintf(L"%c", BODY2);
		}
		pcur = pcur->next;
	}
	ps1->score += ps1->foodweight;
	if (food_eaten == food_num) {
		CreateFood(ps1, ps2, pfood);
	}
	ConsoleTextColor(TEXT_COLOR);
}

void NoFood(SnakeNode* pnext, Snake* ps, int body) {
	pnext->next = ps->snake;
	ps->snake = pnext;
	SnakeNode* pcur = ps->snake;
	while (pcur->next->next != NULL) {
		Setpos(pcur->x, pcur->y);
		if (body == 1) {
			ConsoleTextColor(SNAKE1_COLOR);
			wprintf(L"%lc", BODY1);
		}
		else {
			ConsoleTextColor(SNAKE2_COLOR);
			wprintf(L"%lc", BODY2);
		}
		pcur = pcur->next;
	}
	ConsoleTextColor(TEXT_COLOR);
	Setpos(pcur->next->x, pcur->next->y);
	printf("  ");
	free(pcur->next);
	pcur->next = NULL;
}

void CreateObstacle(Snake* ps1, Snake* ps2) {
	//确定障碍位置
	ConsoleTextColor(OBSTACLE_COLOR);
	int x = 0;
	int y = 0;
	for (int i = 0; i < obstacle_num; i++) {
	again:
		do {
			x = rand() % 65 + 2;
			y = rand() % 33 + 2;
		} while (x % 2 != 0);

		SnakeNode* pcur1 = ps1->snake;
		SnakeNode* pcur2 = ps2->snake;
		while (pcur1 && pcur2) {
			if ((pcur1->x == x && pcur1->y == y) || (pcur2->x == x && pcur2->y == y)) {
				goto again;
			}
			pcur1 = pcur1->next;
			pcur2 = pcur2->next;
		}
		//开辟空间
		SnakeNode* pobstacle = (SnakeNode*)malloc(sizeof(SnakeNode));
		if (pobstacle == NULL) {
			perror("Creatfood:malloc fail!");
			return;
		}
		else {
			pobstacle->x = x;
			pobstacle->y = y;
			Setpos(pobstacle->x, pobstacle->y);
			wprintf(L"%c", OBSTACLE);
			ps1->obstacle[i] = pobstacle;
			ps2->obstacle[i] = pobstacle;
		}
	}
	ConsoleTextColor(TEXT_COLOR);
}

void KillByObstacle(SnakeNode* pnext, Snake* ps) {

	for (int i = 0; i < obstacle_num; i++) {
		if ((pnext->x == ps->obstacle[i]->x) && (pnext->y == ps->obstacle[i]->y)) {
			ps->status = KILL_BY_OBSTACLE;
			MusicPlay(NULL, false, 0);
			PlaySound(L"SnakeDiet.wav", NULL, 0);
			return;
		}
	}
	return;
}

void KillByWall(Snake* ps) {
	if ((ps->snake->x == 0) ||
		(ps->snake->x == 68) ||
		(ps->snake->y == 0) ||
		(ps->snake->y == 35)
		) {
		ps->status = KILL_BY_WALL;
		MusicPlay(NULL, false, 0);
		PlaySound(L"SnakeDiet.wav", NULL, 0);
		return;
	}
	return;
}

void KillBySelf(Snake* ps) {
	assert(ps);
	SnakeNode* pcur = ps->snake->next;
	while (pcur) {
		if ((ps->snake->x == pcur->x) && (ps->snake->y == pcur->y)) {
			ps->status = KILL_BY_SELF;
			MusicPlay(NULL, false, 0);
			PlaySound(L"SnakeDiet.wav", NULL, 0);
			return;
		}
		pcur = pcur->next;
	}
	return;
}

void KillByOther(Snake* ps1, Snake* ps2) {//1撞2死，两蛇通用，调用两次
	SnakeNode* pcur = ps2->snake;
	while (pcur) {
		if ((ps1->snake->x == pcur->x) && (ps1->snake->y == pcur->y)) {
			ps1->status = KILL_BY_OTHER;
			MusicPlay(NULL, false, 0);
			PlaySound(L"SnakeDiet.wav", NULL, 0);
			return;
		}
		pcur = pcur->next;
	}
	return;
}

int GameRun(Snake* ps1, Snake* ps2) {
	MusicPlay(L"SnakeBGM.mp3", true, 250);
	PrintHelpInfo();
	bool pause = false; // 添加一个标志来跟踪游戏是否应该暂停  
	while (ps1->status == OK && ps2->status == OK) {

		if (KEY_PRESS(VK_UP) && ps1->dir != DOWN) {
			ps1->dir = UP;
		}
		// ... (其他ps1的输入处理)  
		else if (KEY_PRESS(VK_DOWN) && ps1->dir != UP)
		{
			ps1->dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps1->dir != RIGHT)
		{
			ps1->dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps1->dir != LEFT)
		{
			ps1->dir = RIGHT;
		}
		else if (KEY_PRESS(VK_W) && ps2->dir != DOWN) {
			ps2->dir = UP;
		}
		else if (KEY_PRESS(VK_S) && ps2->dir != UP)
		{
			ps2->dir = DOWN;
		}
		else if (KEY_PRESS(VK_A) && ps2->dir != RIGHT)
		{
			ps2->dir = LEFT;
		}
		else if (KEY_PRESS(VK_D) && ps2->dir != LEFT)
		{
			ps2->dir = RIGHT;
		}
		else if (KEY_PRESS(VK_F6))
		{
			if (ps2->sleeptime >= 80)
			{
				ps2->sleeptime -= 30;
				ps2->foodweight += 2;
			}
		}
		else if (KEY_PRESS(VK_F7))
		{
			if (ps2->sleeptime < 320)
			{
				ps2->sleeptime += 30;
				ps2->foodweight -= 2;
			}
			if (ps1->status != OK)return 1;
			if (ps1->status != OK)return 2;
		}

		// 处理通用按键（如暂停）  
		if (KEY_PRESS(VK_SPACE) && !pause) { // 只有当游戏没有暂停时才处理空格键  
			pause = true; // 设置暂停标志  
			Pause(); // 暂停游戏  
			pause = false; // 恢复后重置标志  
		}
		if (KEY_PRESS(VK_ESCAPE)) {
			ps1->status = NORMAL_END;
			ps2->status = NORMAL_END;
			ExitGame();
			break;
		}

		// 如果游戏没有暂停，则移动两个蛇  
		if (!pause) {
			SnakeMove(ps1, ps2, 1); // 移动ps1，并检查与ps2的碰撞  
			SnakeMove(ps2, ps1, 2); // 移动ps2，并检查与ps1的碰撞  

			// 休眠以控制游戏速度  
			int minSleepTime = (ps1->sleeptime < ps2->sleeptime) ? ps1->sleeptime : ps2->sleeptime;
			Sleep(minSleepTime);
		}

		// 显示分数信息（可以在每次循环中更新，也可以只在某个蛇状态改变时更新）  
		if (ps1->status == OK && ps2->status == OK) {
			Setpos(80, 10);
			printf("玩家1得分：%d\n", ps1->score);
			Setpos(80, 11);
			printf("玩家2得分：%d\n", ps2->score);
			Setpos(80, 12);
			printf("玩家1每个食物的得分：%2d分\n", ps1->foodweight);
			Setpos(80, 13);
			printf("玩家2每个食物的得分：%2d分\n", ps2->foodweight);

		}

	}
	if (ps1->status != OK)return 1;
	if (ps2->status != OK)return 2;
}

void GameEnd(Snake* ps, int ret) {//两蛇通用，调用两次
	SnakeNode* pcur = ps->snake;
	Setpos(80, 25);
	switch (ps->status) {
	case NORMAL_END:
		printf("玩家%d:您主动退出游戏了。                     ", ret);
		break;
	case KILL_BY_SELF:
		printf("玩家%d:您刚刚撞到自己了。                       ", ret);
		break;
	case KILL_BY_WALL:
		printf("玩家%d:您刚刚撞到墙了。                           ", ret);
		break;
	case KILL_BY_OTHER:
		printf("玩家%d:您刚刚撞到别的蛇了。                        ", ret);
		break;
	case KILL_BY_OBSTACLE:
		printf("玩家%d:您刚刚碰到障碍物了。                       ", ret);
		break;
	}
	while (pcur) {
		SnakeNode* del = pcur;
		pcur = pcur->next;
		free(del);
	}
}

void MusicPlay(const wchar_t* FILENAME, bool x, int audio)
{
	//用于拼接字符串
	wchar_t str[100] = { 0 };
	if (FILENAME != NULL)
	{
		//加载BGM并改别名为BGM
		swprintf(str, sizeof(str) / sizeof(wchar_t), L"open %ls alias BGM", FILENAME);
		mciSendString(str, NULL, 0, NULL);
		//判定是否修改音量
		if (audio)
		{
			swprintf(str, sizeof(str) / sizeof(wchar_t), L"setaudio BGM volume to %d", audio);
			mciSendString(str, NULL, 0, NULL);
		}
		if (x == true)
		{
			//播放BGM
			swprintf(str, sizeof(str) / sizeof(wchar_t), L"play BGM repeat");
			mciSendString(str, NULL, 0, NULL);
		}
	}
	else
	{

		if (audio)
		{
			//判定是否修改音量
			swprintf(str, sizeof(str) / sizeof(wchar_t), L"setaudio BGM volume to %d", audio);
			mciSendString(str, NULL, 0, NULL);
		}
		if (x == false)
		{
			//关闭BGM
			swprintf(str, sizeof(str) / sizeof(wchar_t), L"stop BGM");
			mciSendString(str, NULL, 0, NULL);
		}
	}
}

//控制文字输出颜色
void ConsoleTextColor(WORD wAttributes)
{
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	//看表填颜色数值就行了
	SetConsoleTextAttribute(houtput, wAttributes);
}

void SetObstacleNum(int n)
{
	obstacle_num = n;
}

void SetFoodNum(int n)
{
	food_num = n;
}

//游戏帮助
void help()
{
	cleardevice();
	putimage(0, 0, &img2);
	settextstyle(20, 0, L"黑体");
	settextcolor(BLACK);
	outtextxy(200, 70, L"---本游戏的键盘操控规则---");
	outtextxy(110, 90, L"w or W or ↑ 为向上移动");
	outtextxy(110, 110, L"a or A or ← 为向左移动");
	outtextxy(110, 130, L"s or S or ↓ 为向下移动");
	outtextxy(110, 150, L"d or D or → 为向右移动");
	outtextxy(110, 180, L"F5为加速按钮 按下蛇的移动速度会变快");
	outtextxy(110, 210, L"F6为减速按钮 按下蛇的移动速度会变慢");
	outtextxy(200, 240, L"---本游戏的死亡规则---");
	outtextxy(110, 270, L"当您的蛇头碰到自己其它蛇的身体身体 游戏就会结束");
	outtextxy(110, 300, L"当您的蛇超过了边界范围 游戏就会结束");
	outtextxy(110, 330, L"当您的蛇超过了碰到障碍物 游戏就会结束");
	setbkmode(TRANSPARENT);
	setfillcolor(BROWN);
	fillroundrect(0, 0, 50, 50, 50, 50);
	settextstyle(15, 0, L"黑体");
	int width = textwidth(L"返回");
	int high = textheight(L"返回");
	outtextxy(0 + (50 - width) / 2, 0 + (50 - high) / 2, L"返回");
	while (1)
	{
		ExMessage tmp;
		if (peekmessage(&tmp, EM_MOUSE))
		{
			switch (tmp.message)
			{
			case WM_LBUTTONDOWN:
				if (tmp.x >= 0 && tmp.x <= 50 && tmp.y >= 0 && tmp.y <= 50)
				{
					Menu();
					return;
				}
			}
		}
	}
}
//游戏界面
void Menu()
{
	cleardevice();
	putimage(0, 0, &img1);
	setbkmode(TRANSPARENT);
	setfillcolor(BROWN);
	fillroundrect(400, 300, 400 + 200, 300 + 80, 10, 10);
	settextstyle(30, 0, L"黑体");
	int width = textwidth(L"开始游戏");
	int high = textheight(L"开始游戏");
	outtextxy(400 + (200 - width) / 2, 300 + (80 - high) / 2, L"开始游戏");

	fillroundrect(400, 400, 400 + 200, 400 + 80, 10, 10);
	settextstyle(30, 0, L"黑体");
	width = textwidth(L"游戏帮助");
	high = textheight(L"游戏帮助");
	outtextxy(400 + (200 - width) / 2, 400 + (80 - high) / 2, L"游戏帮助");

	fillroundrect(400, 500, 400 + 200, 500 + 80, 10, 10);
	settextstyle(30, 0, L"黑体");
	width = textwidth(L"游戏设置");
	high = textheight(L"游戏设置");
	outtextxy(400 + (200 - width) / 2, 500 + (80 - high) / 2, L"游戏设置");

	setfillcolor(LIGHTBLUE);
	fillroundrect(900, 10, 900 + 90, 10 + 40, 10, 10);
	settextstyle(20, 0, L"黑体");
	width = textwidth(L"退出");
	high = textheight(L"退出");
	outtextxy(900 + (90 - width) / 2, 10 + (40 - high) / 2, L"退出");

	setfillcolor(LIGHTGREEN);
	fillroundrect(900, 70, 900 + 90, 70 + 40, 10, 10);
	settextstyle(20, 0, L"黑体");
	width = textwidth(L"游戏记录");
	high = textheight(L"游戏记录");
	outtextxy(900 + (90 - width) / 2, 70 + (40 - high) / 2, L"游戏记录");


}
//游戏设置按钮控制
void Set_botton()
{
	int flag_food = 0;
	int flag_obstacle = 0;
	while (1)
	{
		ExMessage tmp;
		ExMessage t;
		BeginBatchDraw();//双缓冲，防止闪屏
		Set();//画界面
		if (peekmessage(&tmp, EM_MOUSE))
		{
			switch (tmp.message)
			{
			case WM_LBUTTONDOWN://点击鼠标左键
				if (tmp.x >= 0 && tmp.x <= 50 && tmp.y >= 0 && tmp.y <= 50)
				{
					botton();
					return;
				}
				if (tmp.x >= 330 && tmp.x <= 370 && tmp.y >= 180 && tmp.y <= 225)//食物减
				{
					if (food_num > 1)
					{
						SetFoodNum(food_num - 1);
					}
				}
				if (tmp.x >= 630 && tmp.x <= 670 && tmp.y >= 180 && tmp.y <= 225)//食物加
				{
					if (food_num < 15)
					{

						SetFoodNum(food_num + 1);
					}
				}
				if (tmp.x >= 330 && tmp.x <= 370 && tmp.y >= 265 && tmp.y <= 305)//障碍物减
				{
					if (obstacle_num > 0)
					{
						SetObstacleNum(obstacle_num - 1);
					}
				}
				if (tmp.x >= 630 && tmp.x <= 670 && tmp.y >= 265 && tmp.y <= 305)//障碍物加
				{
					if (obstacle_num < 15)
					{
						SetObstacleNum(obstacle_num + 1);
					}
				}
				if (tmp.x >= 400 && tmp.x <= 490 && tmp.y >= 340 && tmp.y <= 390)//单人模式
				{

					flag = 1;

				}
				if (tmp.x >= 500 && tmp.x <= 590 && tmp.y >= 340 && tmp.y <= 390)//双人模式
				{
					flag = 2;
				}
			}
		}

		EndBatchDraw();//双缓冲
	}
}
//游戏设置界面
void Set()
{

	cleardevice();
	putimage(0, 0, &img3);

	//设置食物初始个数
	setbkmode(TRANSPARENT);
	setfillcolor(LIGHTBLUE);
	fillroundrect(400, 180, 400 + 200, 180 + 50, 10, 10);
	settextstyle(15, 0, L"黑体");
	settextcolor(BLACK);
	int width = textwidth(L"食物的初始个数为：");
	int high = textheight(L"食物的初始个数为：");
	outtextxy(400 + (200 - width) / 2, 180 + (50 - high) / 2, L"食物的初始个数为：");
	TCHAR s[20];
	_stprintf_s(s, _T("%d"), food_num);
	outtextxy(400 + (200 - width) / 2 + width, 180 + (50 - high) / 2, s);

	setfillcolor(BROWN);
	fillcircle(350, 205, 20);//减
	outtextxy(340, 195, L"一");

	setfillcolor(BROWN);
	fillcircle(650, 205, 20);//加
	outtextxy(642, 195, L"十");

	//设置障碍物初始个数
	setbkmode(TRANSPARENT);
	setfillcolor(LIGHTBLUE);
	fillroundrect(400, 260, 400 + 200, 260 + 50, 10, 10);
	settextstyle(15, 0, L"黑体");
	settextcolor(BLACK);
	width = textwidth(L"障碍物的初始个数为：");
	high = textheight(L"障碍物的初始个数为：");
	outtextxy(400 + (200 - width) / 2, 260 + (50 - high) / 2, L"障碍物的初始个数为：");
	_stprintf_s(s, _T("%d"), obstacle_num);
	outtextxy(400 + (200 - width) / 2 + width, 260 + (50 - high) / 2, s);

	setfillcolor(BROWN);
	fillcircle(350, 285, 20);//减
	outtextxy(340, 275, L"一");

	setfillcolor(BROWN);
	fillcircle(650, 285, 20);//加
	outtextxy(642, 275, L"十");

	//模式选择按钮
	//单人
	setbkmode(TRANSPARENT);
	setfillcolor(LIGHTBLUE);
	fillroundrect(400, 340, 400 + 90, 340 + 50, 10, 10);
	settextstyle(15, 0, L"黑体");
	settextcolor(BLACK);
	width = textwidth(L"单人模式");
	high = textheight(L"单人模式");
	outtextxy(400 + (90 - width) / 2, 340 + (50 - high) / 2, L"单人模式");
	//双人
	setbkmode(TRANSPARENT);
	setfillcolor(LIGHTBLUE);
	fillroundrect(500, 340, 500 + 90, 340 + 50, 10, 10);
	settextstyle(15, 0, L"黑体");
	settextcolor(BLACK);
	width = textwidth(L"双人模式");
	high = textheight(L"双人模式");
	outtextxy(500 + (90 - width) / 2, 340 + (50 - high) / 2, L"双人模式");

	//返回按钮
	setbkmode(TRANSPARENT);
	setfillcolor(BROWN);
	fillroundrect(0, 0, 50, 50, 50, 50);
	settextstyle(15, 0, L"黑体");
	width = textwidth(L"返回");
	high = textheight(L"返回");
	outtextxy(0 + (50 - width) / 2, 0 + (50 - high) / 2, L"返回");
}

//检测按钮是否被点击
bool botton()
{
	EndBatchDraw();//双缓冲，消除闪屏
	Menu();//设置菜单按钮贴图
	ExMessage msg;
	while (1)
	{
		if (peekmessage(&msg, EM_MOUSE))//接受鼠标信息
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN://点击左键
				//帮助界面
				if (msg.x >= 400 && msg.x <= 400 + 200 && msg.y >= 400 && msg.y <= 400 + 80)
				{
					help();
				}
				//设置界面
				if (msg.x >= 400 && msg.x <= 400 + 200 && msg.y >= 500 && msg.y <= 500 + 80)
				{
					Set();
					Set_botton();
					return true;

				}
				//游戏开始
				if (msg.x >= 400 && msg.x <= 400 + 200 && msg.y >= 300 && msg.y <= 300 + 80)
				{
					closegraph();
					return true;
				}
				//退出游戏
				if (msg.x >= 900 && msg.x <= 900 + 90 && msg.y >= 10 && msg.y <= 10 + 40)
				{
					closegraph();
					exit(1);
				}
				//游戏记录
				if (msg.x >= 900 && msg.x <= 900 + 90 && msg.y >= 70 && msg.y <= 70 + 40)
				{
					system("游戏记录.txt");
					
					

				}
			}
		}
	}

}

void start()
{
	initgraph(1000, 600);//画面初始化
	cleardevice();//清空画图设备
	setbkcolor(WHITE);//设置背景颜色为白色
	if (botton())//按钮点击了才清屏进入下一步
	{
		if (flag == 1) {
			run1();
		}
		if (flag == 2)
		{
			run2();
		}

	}
}

int main() {
	loadimage(&img1, L"主背景.png");
	loadimage(&img2, L"帮助背景.png");
	loadimage(&img3, L"设置背景.png");
	start();

	return 0;
}

void RestartGame() {

	MessageBox(NULL, L"游戏重新开始！", L"游戏", MB_OK);

	if (flag == 1) {
		run1();
	}
	if (flag == 2) {
		run2();
	}
}

void ExitGame() {
	start();
}

void run2() {
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));
	Snake snake1 = { 0 };
	Snake snake2 = { 0 };
	GameStart(&snake1, &snake2);
	int ret = GameRun(&snake1, &snake2);
	if (ret == 1) {

		GameEnd(&snake1, ret);
	}
	else {
		GameEnd(&snake2, ret);
	}

	//int ch = 0;
	int cnt = 1;
	int score1[MAXT] = { 0 }, score2[MAXT] = { 0 };
	int result;
	struct tm t;   //tm结构指针
	time_t now;  //声明time_t类型变量
	time(&now);      //获取系统日期和时间
	localtime_s(&t, &now);   //获取当地日期和时间
	score1[cnt - 1] = snake1.score;
	score2[cnt - 1] = snake2.score;
	FILE* fp;
	//追加游戏记录文件
	fp = fopen("游戏记录.txt", "a");
	if (fp == NULL)
	{
		printf("Fail to open record.txt!\n");
		exit(0);
	}

	//打印记录
	for (int i = 1; i <= cnt; i++)
		fprintf(fp, "%14d%14d %15d年/ % d月/ % d日/ %d点/ %d分 /%d秒\n", score1[i - 1], score2[i - 1], t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
	cnt++;

	result = MessageBox(NULL, L"您想重新开始游戏吗？", L"游戏结束", MB_YESNO | MB_ICONQUESTION);

	if (result == IDYES) {
		RestartGame(); // 用户点击“是”，重新开始游戏  
	}
	else {
		fclose(fp);
		ExitGame(); // 用户点击“否”，退出游戏  
	}


}

void run1() {
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));

	Snake snake = { 0 };
	GameStart1(&snake);
	GameRun1(&snake);
	int cnt = 1;
	int score1[MAXT] = { 0 };
	score1[cnt - 1] = snake.score;
	FILE* fp;
	//追加游戏记录文件
	fp = fopen("游戏记录.txt", "a");
	if (fp == NULL)
	{
		printf("Fail to open record.txt!\n");
		exit(0);
	}

	GameEnd1(&snake);
	struct tm t;   //tm结构指针
	time_t now;  //声明time_t类型变量
	time(&now);      //获取系统日期和时间
	localtime_s(&t, &now);   //获取当地日期和时间
	for (int i = 1; i <= cnt; i++)
		fprintf(fp, "%14d%14s %15d年/ % d月/ % d日/ %d点/ %d分 /%d秒\n", score1[i - 1], "无", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
	cnt++;
	Setpos(20, 15);


	int result;
	result = MessageBox(NULL, L"您想重新开始游戏吗？", L"游戏结束", MB_YESNO | MB_ICONQUESTION);
	if (result == IDYES) {
		RestartGame(); // 用户点击“是”，重新开始游戏  
	}
	else {
		ExitGame(); // 用户点击“否”，退出游戏  
	}
}

void InitSnake1(Snake* ps) {
	SnakeNode* pcur = NULL;
	for (int i = 0; i < 5; i++) {
		pcur = (SnakeNode*)malloc(sizeof(SnakeNode));
		if (pcur == NULL) {
			perror("InitSnake:malloc fail!");
			return;
		}
		pcur->next = NULL;
		pcur->x = POS_X1 + i * 2;
		pcur->y = POS_Y1;
		//头插
		if (ps->snake == NULL) {
			ps->snake = pcur;
		}
		else {
			pcur->next = ps->snake;
			ps->snake = pcur;
		}
	}
	//打印蛇身体
	pcur = ps->snake;
	while (pcur) {
		Setpos(pcur->x, pcur->y);
		wprintf(L"%lc", BODY1);
		pcur = pcur->next;
	}
	ps->dir = RIGHT;
	ps->status = OK;
	ps->foodweight = 10;
	ps->score = 0;
	ps->sleeptime = 200;
}

void CreateFood1(Snake* ps, FoodNode* pfood[15]) {
	assert(ps);

	food_eaten = 0;

	for (int i = 0; i < food_num; i++) {
		//确定食物位置
		int x = 0;
		int y = 0;
	again:
		do {
			x = rand() % 65 + 2;
			y = rand() % 33 + 2;
		} while (x % 2 != 0);

		SnakeNode* pcur = ps->snake;

		while (pcur) {
			if (pcur->x == x && pcur->y == y) {
				goto again;
			}
			pcur = pcur->next;
		}

		ConsoleTextColor(FOOD_COLOR);
		pfood[i] = (FoodNode*)malloc(sizeof(FoodNode));

		pfood[i]->x = x;
		pfood[i]->y = y;
		Setpos(pfood[i]->x, pfood[i]->y);
		wprintf(L"%c", FOOD);


	}
	ConsoleTextColor(TEXT_COLOR);
}

void GameStart1(Snake* ps) {
	system("mode con cols=160 lines=40");
	system("title 贪吃蛇");
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(houtput, &CursorInfo);
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(houtput, &CursorInfo);

	Welcome();
	CreateMap();
	InitSnake1(ps);
	CreateFood1(ps, pfood);
	CreateObstacle1(ps);
}

void SnakeMove1(Snake* ps) {
	SnakeNode* pnext = (SnakeNode*)malloc(sizeof(SnakeNode));
	if (pnext == NULL) {
		perror("SnakeMove1:malloc fail!");
		return;
	}

	switch (ps->dir)
	{
	case UP:
		pnext->x = ps->snake->x;
		pnext->y = ps->snake->y - 1;
		break;
	case DOWN:
		pnext->x = ps->snake->x;
		pnext->y = ps->snake->y + 1;
		break;
	case LEFT:
		pnext->x = ps->snake->x - 2;
		pnext->y = ps->snake->y;
		break;
	case RIGHT:
		pnext->x = ps->snake->x + 2;
		pnext->y = ps->snake->y;
		break;
	}

	if (NextIsFood(pnext, ps))
	{
		PlaySound(L"SnakeEat.wav", NULL, 0);
		food_eaten++;
		EatFood1(pnext, ps);
	}
	else
	{
		NoFood1(pnext, ps);
	}

	KillByWall(ps);
	KillBySelf(ps);
	KillByObstacle(pnext, ps);
}

void EatFood1(SnakeNode* pnext, Snake* ps) {
	pnext->next = ps->snake;
	ps->snake = pnext;

	SnakeNode* pcur = ps->snake;
	while (pcur) {
		Setpos(pcur->x, pcur->y);
		wprintf(L"%c", BODY1);
		pcur = pcur->next;
	}
	ps->score += ps->foodweight;
	if (food_eaten == food_num) {
		CreateFood1(ps, pfood);
	}
}

void NoFood1(SnakeNode* pnext, Snake* ps) {
	pnext->next = ps->snake;
	ps->snake = pnext;
	SnakeNode* pcur = ps->snake;
	while (pcur->next->next != NULL) {
		Setpos(pcur->x, pcur->y);
		wprintf(L"%lc", BODY1);
		pcur = pcur->next;
	}
	Setpos(pcur->next->x, pcur->next->y);
	printf("  ");
	free(pcur->next);
	pcur->next = NULL;
}

void GameRun1(Snake* ps) {
	MusicPlay(L"SnakeBGM.mp3", true, 250);
	PrintHelpInfo();
	do {
		Setpos(80, 22);
		printf("得分：%d\n", ps->score);
		Setpos(80, 24);
		printf("每个食物的得分：%2d分\n", ps->foodweight);
		if (KEY_PRESS(VK_UP) && ps->dir != DOWN)
		{
			ps->dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->dir != UP)
		{
			ps->dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT)
		{
			ps->dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT)
		{
			ps->dir = RIGHT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			Pause();
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->status = NORMAL_END;
			break;
		}
		else if (KEY_PRESS(VK_F6))
		{
			if (ps->sleeptime >= 80)
			{
				ps->sleeptime -= 30;
				ps->foodweight += 2;
			}
		}
		else if (KEY_PRESS(VK_F7))
		{
			if (ps->sleeptime < 320)
			{
				ps->sleeptime += 30;
				ps->foodweight -= 2;
			}
		}
		Sleep(ps->sleeptime);
		SnakeMove1(ps);
	} while (ps->status == OK);
}

void GameEnd1(Snake* ps) {
	SnakeNode* pcur = ps->snake;
	Setpos(80, 25);
	switch (ps->status) {
	case NORMAL_END:
		printf("您主动退出游戏了。");
		break;
	case KILL_BY_SELF:
		printf("您撞到自己了。");
		break;
	case KILL_BY_WALL:
		printf("您撞到墙了。");
		break;

	case KILL_BY_OBSTACLE:
		printf("您撞到障碍物了。");
		break;
	}
	while (pcur) {
		SnakeNode* del = pcur;
		pcur = pcur->next;
		free(del);
	}
}

void CreateObstacle1(Snake* ps) {
	//确定障碍位置
	ConsoleTextColor(OBSTACLE_COLOR);
	int x = 0;
	int y = 0;
	for (int i = 0; i < obstacle_num; i++) {
	again:
		do {
			x = rand() % 65 + 2;
			y = rand() % 33 + 2;
		} while (x % 2 != 0);

		SnakeNode* pcur = ps->snake;
		while (pcur) {
			if (pcur->x == x && pcur->y == y) {
				goto again;
			}
			pcur = pcur->next;
		}
		//开辟空间
		SnakeNode* pobstacle = (SnakeNode*)malloc(sizeof(SnakeNode));
		if (pobstacle == NULL) {
			perror("Creatfood:malloc fail!");
			return;
		}
		else {
			pobstacle->x = x;
			pobstacle->y = y;
			Setpos(pobstacle->x, pobstacle->y);
			wprintf(L"%c", OBSTACLE);
			ps->obstacle[i] = pobstacle;
		}
	}
	ConsoleTextColor(TEXT_COLOR);
}